// import Vue from 'vue'
import { mergeRecursive } from '@/utils/cj'
import DictMeta from './DictMeta'
import DictData from './DictData'

const DEFAULT_DICT_OPTIONS = {
  types: [],
}

/**
 * @classdesc 字典
 * @property {Object} label 标签对象，内部属性名为字典类型名称
 * @property {Object} dict 字段数组，内部属性名为字典类型名称
 * @property {Array.<DictMeta>} _dictMetas 字典元数据数组
 */
export default class Dict {
  owner: any
  label: { [key: string]: { [key: string]: string } }
  type: { [key: string]: DictData[] }
  _dictMetas!: DictMeta[]

  constructor() {
    this.owner = null
    this.label = {}
    this.type = {}
  }

  init(options: any): Promise<any[]> {
    if (options instanceof Array) {
      options = { types: options }
    }
    const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
    if (opts.types === undefined) {
      return Promise.reject(new Error('need dict types'))
    }
    const ps: Promise<any>[] = []
    this._dictMetas = opts.types.map((t: any) => DictMeta.parse(t))
    this._dictMetas.forEach((dictMeta) => {
      const type = dictMeta.type
      this.label[type] = {}
      this.type[type] = []
      if (dictMeta.lazy) {
        return
      }
      ps.push(loadDict(this, dictMeta))
    })
    return Promise.all(ps)
  }

  /**
   * 重新加载字典
   * @param {String} type 字典类型
   */
  reloadDict(type: string): Promise<any> {
    const dictMeta = this._dictMetas.find((e) => e.type === type)
    if (dictMeta === undefined) {
      return Promise.reject(`the dict meta of ${type} was not found`)
    }
    return loadDict(this, dictMeta)
  }
}

/**
 * 加载字典
 * @param {Dict} dict 字典
 * @param {DictMeta} dictMeta 字典元数据
 * @returns {Promise}
 */
function loadDict(dict: Dict, dictMeta: DictMeta): Promise<DictData[]> {
  return dictMeta.request(dictMeta).then((response) => {
    const type = dictMeta.type
    let dicts = dictMeta.responseConverter(response, dictMeta)
    if (!(dicts instanceof Array)) {
      console.error('the return of responseConverter must be Array.<DictData>')
      dicts = []
    } else if (dicts.filter((d) => d instanceof DictData).length !== dicts.length) {
      console.error('the type of elements in dicts must be DictData')
      dicts = []
    }
    if (dict.type[type]) {
      dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
      dicts.forEach((d) => {
        if (dict.label[type]) {
          dict.label[type][d.value] = d.label
        }
      })
    }
    return dicts
  })
}